from datetime import datetime
import json
from rest_framework import serializers
from apps.coffee.models import coffee
from apps.users.models import users
from apps.coffee.models import category
from apps.coffee.models import templates
from apps.coffee.models import fields as templates_fields
from apps.coffee.serializers.fields import FieldsSerializer

class CoffeeSerializer(serializers.ModelSerializer):
    """
    用于序列化 coffee 模型的基本信息。
    包含自定义的时间格式化、用户信息和分类信息处理。
    """
    # 使用 SerializerMethodField 自定义 create_time 字段的序列化逻辑
    create_time = serializers.SerializerMethodField()
    # 使用 SerializerMethodField 自定义 update_time 字段的序列化逻辑
    update_time = serializers.SerializerMethodField()
    # 使用 SerializerMethodField 自定义 user_info 字段的序列化逻辑
    user_info = serializers.SerializerMethodField()
    # 使用 SerializerMethodField 自定义 category 字段的序列化逻辑
    category = serializers.SerializerMethodField()

    class Meta:
        """
        元类，用于配置序列化器的元数据。
        """
        model = coffee  # 指定关联的模型为 coffee
        # 指定序列化时包含的字段
        fields = ['id','title','description','user_info','cover','category','category_id','create_time','update_time','user_id','recommend','views','likes','status']

    def get_create_time(self, obj):
        """
        自定义 create_time 字段的序列化方法。
        将时间戳转换为指定格式的日期字符串。

        :param obj: coffee 模型实例
        :return: 格式化后的日期字符串或 None
        """
        if obj.create_time:
            return datetime.fromtimestamp(obj.create_time).strftime('%Y-%m-%d %H:%M:%S')
        return None

    def get_update_time(self, obj):
        """
        自定义 update_time 字段的序列化方法。
        将时间戳转换为指定格式的日期字符串。

        :param obj: coffee 模型实例
        :return: 格式化后的日期字符串或 None
        """
        if obj.update_time:
            return datetime.fromtimestamp(obj.update_time).strftime('%Y-%m-%d %H:%M:%S')
        return None

    def get_user_info(self, obj):
        """
        自定义 user_info 字段的序列化方法。
        根据用户 ID 获取用户信息。

        :param obj: coffee 模型实例
        :return: 包含用户 ID 和用户名的字典
        """
        user_obj = users.objects.get(id=obj.user_id)
        return {
            'user_id': user_obj.id,
            'username': user_obj.username
        }

    def get_category(self, obj):
        """
        自定义 category 字段的序列化方法。
        从 JSON 字符串中解析分类 ID 并获取对应的分类信息。

        :param obj: coffee 模型实例
        :return: 包含分类 ID 和名称的查询集或 None
        """
        # category_obj = category.objects.get(id__in=obj.category).values('id', 'name')
        ids = obj.category if isinstance(obj.category, str) else None
        if ids:
            try:
                ids = json.loads(ids)
                category_obj = category.objects.filter(id__in=ids).values('id', 'name')
            except (json.JSONDecodeError, TypeError):
                category_obj = None
        return category_obj

class CoffeeDetailSerializer(serializers.ModelSerializer):
    """
    用于序列化 coffee 模型的详细信息。
    包含自定义的时间格式化、内容处理、分类信息和自定义字段处理等。
    """
    # 使用 SerializerMethodField 自定义 create_time 字段的序列化逻辑
    create_time = serializers.SerializerMethodField()
    # 使用 SerializerMethodField 自定义 content 字段的序列化逻辑
    content = serializers.SerializerMethodField()
    # 使用 SerializerMethodField 自定义 category 字段的序列化逻辑
    category = serializers.SerializerMethodField()
    # 使用 SerializerMethodField 自定义 category_id 字段的序列化逻辑
    category_obj = serializers.SerializerMethodField()
    # 使用 SerializerMethodField 自定义 custom_fields 字段的序列化逻辑
    custom_fields = serializers.SerializerMethodField()
    # 使用 SerializerMethodField 自定义 gallery 字段的序列化逻辑
    gallery = serializers.SerializerMethodField()
    # 使用 SerializerMethodField 自定义 template 字段的序列化逻辑
    template_fields = serializers.SerializerMethodField()

    class Meta:
        """
        元类，用于配置序列化器的元数据。
        """
        model = coffee  # 指定关联的模型为 coffee
        fields = '__all__'  # 包含模型的所有字段

    def get_create_time(self, obj):
        """
        自定义 create_time 字段的序列化方法，复用 CoffeeSerializer 的逻辑。

        :param obj: coffee 模型实例
        :return: 格式化后的日期字符串或 None
        """
        return CoffeeSerializer.get_create_time(self, obj)

    def get_update_time(self, obj):
        """
        自定义 update_time 字段的序列化方法，复用 CoffeeSerializer 的逻辑。

        :param obj: coffee 模型实例
        :return: 格式化后的日期字符串或 None
        """
        return CoffeeSerializer.get_update_time(self, obj)

    def get_content(self, obj):
        """
        自定义 content 字段的序列化方法。
        直接返回对象的 content 属性，转义 HTML 存储字符。

        :param obj: coffee 模型实例
        :return: 对象的 content 属性值
        """
        # 转义 html 存储字符
        return obj.content

    # 定义一个方法，用于从对象中获取指定键的 JSON 数据并进行解析
    # key: 要从对象中获取的键名
    # obj: 包含 JSON 数据的对象
    def get_json_data(self, obj, key):
        """
        从对象中获取指定键的 JSON 数据并进行解析。

        :param obj: 包含 JSON 数据的对象
        :param key: 要获取的键名
        :return: 解析后的 JSON 数据或 None
        """
        try:
            # 使用 getattr 安全访问属性
            value = getattr(obj, key, "")
            return json.loads(value) if value else None
        except (json.JSONDecodeError, TypeError, AttributeError):
            return None

    def get_category(self, obj):
        """
        自定义 category 字段的序列化方法，复用 get_json_data 方法。

        :param obj: coffee 模型实例
        :return: 解析后的分类信息或 None
        """
        return self.get_json_data(obj, 'category')

    def get_custom_fields(self, obj):
        """
        自定义 custom_fields 字段的序列化方法，复用 get_json_data 方法。

        :param obj: coffee 模型实例
        :return: 解析后的自定义字段信息或 None
        """
        return self.get_json_data(obj, 'custom_fields')

    def get_gallery(self, obj):
        """
        自定义 gallery 字段的序列化方法，复用 get_json_data 方法。

        :param obj: coffee 模型实例
        :return: 解析后的图库信息或 None
        """
        return self.get_json_data(obj, 'gallery')

    def get_template_fields(self, obj):
        """
        自定义 template 字段的序列化方法。
        检查模板是否存在并返回对应的模板信息。

        :param obj: coffee 模型实例
        :return: 模板信息查询集或 None
        """
        # 优化查询：使用 exists() 检查存在性
        
        if templates.objects.filter(id=obj.template).exists():
            template =  templates.objects.get(pk=obj.template)
            f = getattr(template,'fields','')
            try:
                ids = json.loads(f)
                tf = templates_fields.objects.all().filter(id__in=ids).order_by('id')
                return FieldsSerializer(tf,many=True).data
            except (json.JSONDecodeError,TypeError):
                return None
        #return fields_id
    def get_category_obj(self,obj):
        ids = self.get_json_data(obj,'category')
        category_obj = category.objects.all().filter(id__in=ids).values('id','name')
        return category_obj